<template>
  <div id="HelloWorld">
    <div id="toolPlan">
      <div class="node radius" id="node1" >开始</div>
      <div class="node" style="top: 120px" id="node2">节点</div>
    </div>
    <div id="main">
      <div id="diagramContainer">
      </div>
    </div>
    <div id="operPlan">
      <button @click="saveData">保存数据</button>
      <button @click="loadData">读取数据</button>
    </div>
  </div>
</template>

<script>
  import jsplumb from 'jsplumb';
  import 'jquery-ui/ui/widgets/draggable'
  import 'jquery-ui/ui/widgets/droppable'
  import 'jquery-ui/ui/widgets/resizable'
export default {
  name: 'HelloWorld',
  data () {
    return {
      jsPlumb : {},
      UUID : require('uuid'),
      common : {
        isSource: true,
        isTarget: true,
        connector: 'Flowchart',  //连接线线性
        hoverPaintStyle: {
          outlineStroke: 'green',
          fill: 'green'
        }, //鼠标悬停在端点样式
        endpointHoverStyle:{
          fill: 'green'
        },
        paintStyle: { fill:'#456',stroke: '#456',radius:3}, //端点样式
        maxConnections: -1,  //端点最大连接数 -1为无限制
        connectorOverlays: [["Arrow", { width: 12, length: 12, location: 1 }]]  //端点箭头样式
      },
      activeNode:'',
    }
  },
  methods:{
    /**
     * 保存图形数据
     */
    saveData(){
      //节点信息
      const nodesInfo=this.jsPlumb.getManagedElements(),ledgeInfo=this.jsPlumb.getAllConnections(),nodes=[],ledges=[];
      let temp;
      for(let item in nodesInfo){
        if(nodesInfo.hasOwnProperty(item)){
          temp=nodesInfo[item];
          nodes.push({
            id:$(nodesInfo[item].el).attr('id'),
            left:parseInt(temp.info.o.left),
            top:parseInt(temp.info.o.top),
            text:temp.el.innerText,
            anchors:this.jsPlumb.getEndpoints(temp.el).map(i=>{return i.getUuid()}),
            classList:temp.el.className.split(" "),
          })
        }
      }
      //边信息
      for(let item in ledgeInfo){
        if(ledgeInfo.hasOwnProperty(item)){
          temp=ledgeInfo[item];
          ledges.push({
            source:{id:temp.sourceId,uuid:temp.endpoints[0].getUuid()},
            target:{id:temp.targetId,uuid:temp.endpoints[1].getUuid()}
          });
        }
      }
      const datas={
        nodes:nodes,
        ledges:ledges
      };
      //datas为图形数据，在http请求中将datas直接作为传输数据对
      console.log(datas)
    },
    /**
     * 装载数据，渲染图形
     * @param data string类型，是json对应的字符串
     */
    loadData(data){
      data.nodes.forEach(item=>{
       this.addNode(item);
      });
      data.ledges.forEach(item=>{
        this.jsPlumb.connect({ uuids: [item.source.uuid, item.target.uuid] })
      })
    },
    /**
     * 添加节点，并且为节点添加四周端点、可拖拽、双击事件、悬停显示删除按钮
     * @param node json对象，包含了id、left、top、classList、text
     */
    addNode(node){
      $('#diagramContainer').append('<div class="'+node.classList.join(" ")+'" id="' + node.id + '" >' + node.text + '</div>');
      $('#'+node.id).append('<img id="'+node.id+'-img" style="position:absolute;display:none;width: 50px"  src=""  />');
      $('#'+node.id+"-img").css("left", 55).css("top", -20);
      $("#" + node.id).css("left", node.left).css("top", node.top);
      this.addEndpoint(node.id,this.common,node.anchors);
      this.draggable(node.id);
      this.deleteNode(node);
      this.doubleclick(node.id);
    },
    /**
     * 为节点添加四周端点
     * @param id 节点ID
     * @param common 绘制节点的默认参数
     * @param anchor 端点UUID数组
     */
    addEndpoint(id,common={},anchor=[]) {
      if(anchor.length>0){
        this.jsPlumb.addEndpoint(id, {
          anchors: ['Top'],
          uuid:anchor[0]
        },common);
        this.jsPlumb.addEndpoint(id, {
          anchors: ['Right'],
          uuid:anchor[1]
        },common);
        this.jsPlumb.addEndpoint(id, {
          anchors: ['Bottom'],
          uuid:anchor[2]
        },common);
        this.jsPlumb.addEndpoint(id, {
          anchors: ['Left'],
          uuid:anchor[3]
        },common);
      }else{
        this.jsPlumb.addEndpoint(id, {
          anchors: ['Top'],
          uuid:this.UUID.v1()
        },common);
        this.jsPlumb.addEndpoint(id, {
          anchors: ['Right'],
          uuid:this.UUID.v1()
        },common);
        this.jsPlumb.addEndpoint(id, {
          anchors: ['Bottom'],
          uuid:this.UUID.v1()
        },common);
        this.jsPlumb.addEndpoint(id, {
          anchors: ['Left'],
          uuid:this.UUID.v1()
        },common);
      }
    },
    /**
     * 允许节点拖拽且网格对齐
     * @param id 节点ID
     */
    draggable(id) {
      this.jsPlumb.draggable(id,{
        containment: 'parent',
        grid: [10, 10]
      })
    },
    /**
     * 双击节点触发事件
     * @param id
     */
    doubleclick(id) {
      const _this=this;
      $("#"+id).dblclick(function () {
        _this.activeNode=id;
      });
    },
    /**
     * 鼠标悬停 显示可删除按钮
     * @param node
     */
    deleteNode (node) {
      const _this=this;
    $("#" + node.id).mouseenter(function () {
      $('#'+node.id+"-img").show();
    });
    $("#" + node.id+"-img").click(function () {
      _this.jsPlumb.remove(node.id);
    });
    $("#" + node.id).mouseleave(function () {
      $('#'+node.id+"-img").hide();
    });
  }
  },
  watch:{
    activeNode:function(value){
      console.log(value)
    }
  },
  mounted(){
    const jsPlumb=jsplumb.jsPlumb;
    this.jsPlumb=jsPlumb;
    const _this=this;
    jsPlumb.ready(function() {
      jsPlumb.setContainer('diagramContainer'); //节点只能在固定该区域内移动。

      //模拟通过网络请求装载数据，渲染图形
      setTimeout(function () {
        let str='{"nodes":[{"id":"433c4cd0-74c7-11e9-b96d-f9e0e5988752","left":175,"top":61,"text":"开始","anchors":["433c9af0-74c7-11e9-b96d-f9e0e5988752","433ee4e0-74c7-11e9-b96d-f9e0e5988752","433f3300-74c7-11e9-b96d-f9e0e5988752","433f3301-74c7-11e9-b96d-f9e0e5988752"],"classList":["node","radius","jtk-endpoint-anchor","jtk-managed","jtk-draggable","jtk-connected"]},{"id":"43df6aa0-74c7-11e9-b96d-f9e0e5988752","left":331,"top":197,"text":"节点","anchors":["43df6aa1-74c7-11e9-b96d-f9e0e5988752","43df91b0-74c7-11e9-b96d-f9e0e5988752","43dfb8c0-74c7-11e9-b96d-f9e0e5988752","43dfdfd0-74c7-11e9-b96d-f9e0e5988752"],"classList":["node","jtk-endpoint-anchor","jtk-managed","jtk-draggable","jtk-connected"]},{"id":"44e011c0-74c7-11e9-b96d-f9e0e5988752","left":527,"top":60,"text":"节点","anchors":["44e011c1-74c7-11e9-b96d-f9e0e5988752","44e05fe0-74c7-11e9-b96d-f9e0e5988752","44e086f0-74c7-11e9-b96d-f9e0e5988752","44e0ae00-74c7-11e9-b96d-f9e0e5988752"],"classList":["node","jtk-endpoint-anchor","jtk-managed","jtk-draggable","jtk-connected"]},{"id":"5bdb6690-74c7-11e9-994f-f14462740e9f","left":799,"top":63,"text":"节点","anchors":["5bdb6691-74c7-11e9-994f-f14462740e9f","5bdbdbc0-74c7-11e9-994f-f14462740e9f","5bdc02d0-74c7-11e9-994f-f14462740e9f","5bdc29e0-74c7-11e9-994f-f14462740e9f"],"classList":["node","jtk-endpoint-anchor","jtk-managed","jtk-draggable","jtk-connected"]},{"id":"733fdd70-74c7-11e9-9b6c-ad7a48866764","left":999,"top":64,"text":"节点","anchors":["733fdd71-74c7-11e9-9b6c-ad7a48866764","73402b90-74c7-11e9-9b6c-ad7a48866764","734052a0-74c7-11e9-9b6c-ad7a48866764","734052a1-74c7-11e9-9b6c-ad7a48866764"],"classList":["node","jtk-endpoint-anchor","jtk-managed","jtk-draggable","jtk-connected"]}],"ledges":[{"source":{"id":"433c4cd0-74c7-11e9-b96d-f9e0e5988752","uuid":"433f3300-74c7-11e9-b96d-f9e0e5988752"},"target":{"id":"43df6aa0-74c7-11e9-b96d-f9e0e5988752","uuid":"43df6aa1-74c7-11e9-b96d-f9e0e5988752"}},{"source":{"id":"43df6aa0-74c7-11e9-b96d-f9e0e5988752","uuid":"43df91b0-74c7-11e9-b96d-f9e0e5988752"},"target":{"id":"44e011c0-74c7-11e9-b96d-f9e0e5988752","uuid":"44e086f0-74c7-11e9-b96d-f9e0e5988752"}},{"source":{"id":"44e011c0-74c7-11e9-b96d-f9e0e5988752","uuid":"44e05fe0-74c7-11e9-b96d-f9e0e5988752"},"target":{"id":"5bdb6690-74c7-11e9-994f-f14462740e9f","uuid":"5bdc29e0-74c7-11e9-994f-f14462740e9f"}},{"source":{"id":"5bdb6690-74c7-11e9-994f-f14462740e9f","uuid":"5bdbdbc0-74c7-11e9-994f-f14462740e9f"},"target":{"id":"733fdd70-74c7-11e9-9b6c-ad7a48866764","uuid":"734052a1-74c7-11e9-9b6c-ad7a48866764"}}]}';
        _this.loadData(JSON.parse(str));
      },1000);

      //一般来说拖动创建的链接，可以再次拖动，让链接断开。如果不想触发这种行为，可以设置。
      jsPlumb.importDefaults({
        ConnectionsDetachable: false,
      });

       $("#toolPlan").children().draggable({
        helper: "clone",
        scope: "plan",//值随意命名
      });

      $("#diagramContainer").droppable({
        scope: "plan",
        drop: function (event, ui) {
          _this.addNode({
            id:_this.UUID.v1(),
            left:parseInt(ui.offset.left - $(this).offset().left),
            top:parseInt(ui.offset.top - $(this).offset().top),
            text:$(ui.helper).html(),
            classList:ui.draggable[0].className.split(" ")
          });
        }
      });
      jsPlumb.bind('click', function (conn) {
        if (window.prompt('确定删除所点击的链接吗？ 输入1确定') === '1') {
          jsPlumb.detach(conn)
        }
      });

      //当链接建立前判定,防止同一节点自环
      jsPlumb.bind('beforeDrop', function (conn) {
        return conn.sourceId !== conn.targetId;
      })
    });

  }
}
</script>

<style>
#HelloWorld{
  position: relative;
}
  #toolPlan{
    width: 19%;
    height: 400px;
    border: 1px solid gray;
    left: 0;
    position: absolute;
  }
  #main{
    left: 20%;
    width: 60%;
    height: 400px;
    position: absolute;
  }
  #operPlan{
    right: 0;
    width: 19%;
    height: 400px;
    border: 1px solid gray;
    position: absolute;
  }
  #diagramContainer {
    position: relative;
    float: left;
    width: 100%;
    height: 100%;
    border: 1px solid gray;
    background-repeat: repeat;
  }
  .node {
    box-shadow: 2px 2px 19px #aaa;
    -o-box-shadow: 2px 2px 19px #aaa;
    -webkit-box-shadow: 2px 2px 19px #aaa;
    -moz-box-shadow: 2px 2px 19px #aaa;
    -moz-border-radius: 0.5em;
    border-radius: 0.5em;
    opacity: 0.8;
    filter: alpha(opacity=80);
    border: 1px solid #346789;
    width: 60px;
    text-align: center;
    z-index: 20;
    position: absolute;
    background-color: #eeeeef;
    color: black;
    padding: 10px;
    font-size: 9pt;
    cursor: pointer;
    height: 30px;
    line-height: 30px;
  }
  .radius {
    border-radius: 25em;
  }
  .node:hover {
    box-shadow: 2px 2px 19px #444;
    -o-box-shadow: 2px 2px 19px #444;
    -webkit-box-shadow: 2px 2px 19px #444;
    -moz-box-shadow: 2px 2px 19px #444;
    opacity: 0.8;
    filter: alpha(opacity=80);
  }
  .jtk-endpoint{
    z-index: 21;

  }
  .jtk-endpoint:hover{
    cursor: pointer;
  }
</style>
